/*
 * @Author: 13938960424 1758142861@qq.com
 * @Date: 2023-10-27 17:55:22
 * @LastEditors: 13938960424 1758142861@qq.com
 * @LastEditTime: 2023-10-31 15:29:21
 * @FilePath: /sjf/new-xshell/muduo/source/channel.hpp
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
#pragma once

#include <iostream>
#include <functional>
#include <vector>
#include <cstring>
#include <cassert>
#include <sys/epoll.h>
#include <unordered_map>
//#include "poller.hpp"
#include "eventloop.hpp"
#include "../log/logger.hpp"
using EventCallBack = std::function<void()>;
class Poller;
class EventLoop;
class Channel
{
public:
    Channel(int fd,EventLoop* loop):_fd(fd),_loop(loop),_events(0),_revents(0) {}
    int Fd() { return _fd; }
    //获取事件
    uint32_t Events() {return _events;}
    void SetREvent(uint32_t events) { _revents = events; }
    //设置读事件回调
    void SetReadCallback(const EventCallBack &cb) {_read_callback = cb;} 
    //设置写事件回调
    void SetWriteCallback(const EventCallBack &cb) {_write_callback = cb;}
    //设置错误事件回调
    void SetErrorCallback(const EventCallBack &cb) {_error_callback = cb;}
    //设置关闭事件回调
    void SetCloseCallback(const EventCallBack &cb) {_close_callback = cb;}
    //设置所有事件回调
    void SetEventCallback(const EventCallBack &cb) {_event_callback = cb;}
    //当前是否监控可读
    bool ReadAble() { return (_events & EPOLLIN); }
    //当前是否监控可写
    bool WriteAble() { return (_events & EPOLLOUT); }
    //设置可读
    void EnableRead() { _events |= EPOLLIN; Update(); }
    //设置可写
    void EnableWrite() { _events |= EPOLLOUT; Update();}
    //删除可读
    void DisableRead() { _events &= ~EPOLLIN; Update(); }
    //删除可写
    void DisableWrite() { _events &= ~EPOLLOUT; Update(); } 
    //删除所有
    void DisableAll() { _events = 0; Update(); }
    //移除事件
    void Remove();
    //事件的新增/增信
    void Update();
    //事件处理,一旦连接触发了事件,就调用该函数,进行事件的回调
    void HandleEvent()
    {
        if((_revents & EPOLLIN) || (_revents & EPOLLRDHUP) || (_revents & EPOLLPRI))
        {
            if(_event_callback)
                _event_callback();
            if(_read_callback) 
                _read_callback();
        }
        if(_revents & EPOLLOUT)
        {
            if(_write_callback)
                _write_callback();
        }
        else if(_revents & EPOLLERR)
        {
            if(_error_callback)
                _error_callback();
        }
        else if(_revents & EPOLLHUP)
        {
            if(_close_callback)
                _close_callback();
        }
            
        //任意事件回调调用
        if(_event_callback)
            _event_callback();
    }

private:
    int _fd;
    //Poller *_poller;
    EventLoop* _loop;
    uint32_t _events;//当前需要监控的事件
    uint32_t _revents;//当前连接触发的事件
    EventCallBack _read_callback; //可读事件回调
    EventCallBack _write_callback;//可写事件回调
    EventCallBack _close_callback;//关闭事件回调
    EventCallBack _error_callback;//错误事件回调
    EventCallBack _event_callback;//任意事件回调
};

#define MAX_EPOLLEVENTS 1024
class Poller
{
public:
    Poller()
    {
        _epfd = epoll_create(MAX_EPOLLEVENTS);
        if(_epfd < 0)
        {
            ERR_LOG("epoll_create error,code:%d,errstring:%s",errno,strerror(errno));
            abort();
        }
    };
    //添加/修改监控事件
    void UpdateEvent(Channel* channel)
    {
        bool ret = HasChannel(channel);
        if(ret == false)
        {
            //没有就添加
            _channels.insert(std::make_pair(channel->Fd(),channel));
            return Update(channel,EPOLL_CTL_ADD);
        }
        return Update(channel,EPOLL_CTL_MOD);
    }
    //移除监控事件
    void RemoveEvent(Channel* channel)
    {
        auto it = _channels.find(channel->Fd());
        if(it != _channels.end())
            _channels.erase(it);
        Update(channel,EPOLL_CTL_DEL);
    }
    //开始监控，返回连接
    void Poll(std::vector<Channel*> *active)
    {
        //对于timeout,后序修改
        int nfds = epoll_wait(_epfd,_evs,MAX_EPOLLEVENTS,-1);
        if(nfds < 0)
        {
            if(errno == EINTR)
                return;
            ERR_LOG("epoll_wait error:%s\n",strerror(errno));
            abort();
        }
        for(int i = 0; i < nfds; i++)
        {
           auto it = _channels.find(_evs[i].data.fd);
           assert(it != _channels.end());
           it->second->SetREvent(_evs[i].events);
           active->push_back(it->second);
        }
        return;
    }
private:
    //对epoll直接接口调用
    void Update(Channel* channel,int op)
    {
        //int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
        int fd = channel->Fd();
        struct epoll_event ev;
        ev.data.fd = fd;
        ev.events = channel->Events();
        int ret = epoll_ctl(_epfd,op,fd,&ev);
        if(ret < 0)
        {
            ERR_LOG("epoll_ctl error!");
            abort();//直接退出程序
        }
        return;
    }
    //判断一个channel是否添加了事件监控
    bool HasChannel(Channel* channel)
    {
        auto it = _channels.find(channel->Fd());
        if(it == _channels.end())
            return false;
        return true;
    }
private:
    int _epfd;
    struct epoll_event _evs[MAX_EPOLLEVENTS];
    std::unordered_map<int,Channel*> _channels;
};

//移除事件
void Channel::Remove() { _loop->RemoveEvent(this); }
    //事件的新增/增信
void Channel::Update() { _loop->UpdateEvent(this); }